import axios, {AxiosError, AxiosRequestConfig, AxiosResponse, Method} from 'axios';
import {ElMessage} from 'element-plus';

// 创建 Axios 实例
const instance = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL, // 从 Vite 环境变量读取
    timeout: 10000,
    withCredentials: true, // 允许跨域携带 Cookie
});

// 请求拦截器（添加 Token）
instance.interceptors.request.use(
    (config: AxiosRequestConfig) => {
        const token = localStorage.getItem('token');
        if (token) {
            config.headers = {
                ...config.headers,
                Authorization: `Bearer ${token}`,
            };
        }
        return config;
    },
    (error: AxiosError) => {
        ElMessage.error('请求发送失败');
        return Promise.reject(error);
    }
);

// 响应拦截器（统一错误处理）
instance.interceptors.response.use(
    (response: AxiosResponse) => {
        if (response.data.code === 200) {
            //HTTP 成功 + 业务成功	拦截器 if 分支	返回 data
            return response.data.data; // 直接返回业务数据
        } else {
            //HTTP 成功 + 业务失败	拦截器 else 分支	手动 reject
            //else 是开发者主动控制的业务错误分支，需手动 reject。
            //两者最终都会进入 Promise 的 catch，但错误来源不同。
            ElMessage.error(response.data.message || '操作失败');
            return Promise.reject(response.data);
        }
    },
    (error: AxiosError) => {
        // 处理 HTTP 错误（401/403/404/500...）
        // 拦截器的 reject 回调是Axios 自动触发的 HTTP 错误分支。
        //两者最终都会进入 Promise 的 catch，但错误来源不同。
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    ElMessage.error('请先登录');
                    break;
                case 403:
                    ElMessage.error('没有权限');
                    break;
                case 404:
                    ElMessage.error('接口不存在');
                    break;
                default:
                    ElMessage.error('服务器错误');
            }
        } else if (error.code === 'ECONNABORTED') {
            ElMessage.error('请求超时');
        } else {
            ElMessage.error('网络错误');
        }
        return Promise.reject(error);
    }
);

/**
 * 封装通用请求方法（GET/POST/PUT/DELETE）
 * @param method 请求方法
 * @param url 接口地址
 * @param data 请求数据（POST/PUT 用 data，GET/DELETE 用 params）
 * @param config 额外 Axios 配置
 */
//T：表示请求返回的数据类型
//= any：如果不指定 T，则默认返回 any 类型（即不进行类型检查）。
//?: 表示该参数是可选的
export function request<T = any>(
    method: Method,
    url: string,
    data?: any,
    config?: AxiosRequestConfig
): Promise<T> {
    return instance({
        method,
        url,
        ...(method === 'get' || method === 'delete' ? {params: data} : {data}),
        //条件：如果 method 是 'get' 或 'delete'，返回 { params: data }，否则返回 { data }。
        // GET/DELETE 请求：数据应放在 params 中（最终拼接到 URL 的查询参数）。
        // POST/PUT 请求：数据应放在 data 中（作为请求体发送）。
        ...config,
    });
}

// 示例：直接导出常用方法（可选）
export const get = <T = any>(url: string, params?: any, config?: AxiosRequestConfig) =>
    request<T>('get', url, params, config);

export const post = <T = any>(url: string, data?: any, config?: AxiosRequestConfig) =>
    request<T>('post', url, data, config);

export const put = <T = any>(url: string, data?: any, config?: AxiosRequestConfig) =>
    request<T>('put', url, data, config);

export const del = <T = any>(url: string, params?: any, config?: AxiosRequestConfig) =>
    request<T>('delete', url, params, config);

// 默认导出 Axios 实例（以防需要直接调用）
export default instance;